package com.san.simulation.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.san.simulation.model.api.Element;
import com.san.simulation.model.api.ElementType;
import com.san.simulation.model.api.Path;
import com.san.simulation.model.impl.ActivitiProcessPath;

public class PathResolverHelper {
	
	private int pathIndex = 0;

	private List<Element> parentActivities = new ArrayList<Element>();
	private List<Path> allpaths = new ArrayList<Path>();
	private List<String> visitedPath= new ArrayList<String>();
	
	private Path currentPath;
	
	public Path newPath() {
		this.currentPath = newProcessPath(pathIndex);
		pathIndex++;
		
		this.currentPath.addAllPathActivities(parentActivities);
		
		return this.currentPath;
	}
	
	public void addParentElement(Element element) {
		if (!this.parentActivities.contains(element)) {
			this.parentActivities.add(element);
		}
	}
	
	public boolean hasCurrentPath() {
		return this.currentPath != null;
	}
	
	public boolean triggerNewPath(Element element) {
		
		if (ElementType.EXCLUSIVE_GATEWAY.isValid(element.getType()) 
				&& "diverging".equalsIgnoreCase((String) element.getProperty("gatewayDirection"))) {
			return true;
		} 
		// make sure parallel gateways will not trigger new paths
		else if (ElementType.PARALLEL_GATEWAY.isValid(element.getType())) {
			return false;
		} 
		// if there are more than one outgoing transition, it means there will be a split
		else if (element.getOutgoingTransitions() != null && element.getOutgoingTransitions().size() > 1) {
			return true;
		}
		
		return false;
	}
	
	public void removeCurrentLevelFromParentElements(Element element) {
		if (currentPath != null && this.parentActivities.size() >= 2) {
			
			if (this.parentActivities.lastIndexOf(element) == (parentActivities.size()-1)) {
				this.parentActivities.remove(parentActivities.size()-1);
				this.parentActivities.remove(parentActivities.size()-1);
			} else {
				this.parentActivities.remove(parentActivities.size()-1);
			}
		}
	}
	
	public List<Path> getPaths() {
		if (currentPath == null && allpaths.isEmpty() && !parentActivities.isEmpty()) {
			newPath();
			finalizePath();
		}
		
		for (Path path : this.allpaths) {
			List<Element> act = path.getPathElements();
			
			Collections.sort(act, new Comparator<Element>() {

				public int compare(Element object1, Element object2) {
					
					return object1.getLevel() - object2.getLevel();
				}
			});
			
		}
		
		return this.allpaths;
	}
	
	public void finalizePath() {
		if (this.currentPath != null && !allpaths.contains(currentPath)) {
			this.allpaths.add(currentPath);
//			currentPath = null;
		}
		
	}

	public void addCurrentPathActivity(Element activity) {
		if (!this.currentPath.getPathElements().contains(activity)) {
			this.currentPath.addPathActivity(activity);
		}
		
	}
	
	public Path newProcessPath(int index) {
		return new ActivitiProcessPath("path-" + index);
	}

	public List<String> getVisitedPath() {
		return visitedPath;
	}

	public void setVisitedPath(List<String> visitedPath) {
		this.visitedPath = visitedPath;
	}
	
	public void addVisitedPath(String pathId){
		this.visitedPath.add(pathId);
	}

	public Path getCurrentPath() {
		return currentPath;
	}

	public void setCurrentPath(Path currentPath) {
		this.currentPath = currentPath;
	}
	
	
	
}